package com.huika.dealontop.utils;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;

import com.google.android.gms.maps.model.LatLng;
import com.huika.dealontop.R;
import com.huika.dealontop.control.homepage.Interface.StopRefreshInterface;
import com.huika.dealontop.views.ToastMsg;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


/**
 * @author chenyuan
 * @description：Google地图工具类
 * @date 2015年11月16日 上午11:25:04
 */
public class GMapUtil {

    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
    private Activity activity;
    private GMapUtil gMapHelper = null;
    private LocationManager locationManager;
    private String provider;
    private Location location;

    /**
     * addressDetail的所有拼接地址
     */
    public ArrayList<String> addressDatas = new ArrayList<String>();
    public String addressDetail;

    public interface MyLocationListener {
        public void getLatestAddress(String latestAddress);
    }

    public interface MyLocationCityListener {
        public void getLatestCityAddress(String latestCityAddress);
    }

    private MyLocationListener myLocationListener;
    private MyLocationCityListener myLocationCityListener;

    public GMapUtil getInstance() {
        if (gMapHelper == null) {
            gMapHelper = new GMapUtil();
        }
        return gMapHelper;
    }

    public GMapUtil() {
    }

    public GMapUtil(Activity act) {
        activity = act;
    }

    public GMapUtil(Activity act, MyLocationListener mMyLocationListener) {
        activity = act;
        this.myLocationListener = mMyLocationListener;
    }

    public GMapUtil(Activity act, MyLocationCityListener myLocationCityListener) {
        activity = act;
        this.myLocationCityListener = myLocationCityListener;
    }

    /**
     * google 定位，保证GPS打开
     **/
    public void requestGMapLocation() {

        locationManager = (LocationManager) activity
                .getSystemService(Context.LOCATION_SERVICE);
        if (locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
//            ToastMsg.showToastMsg(activity, "GPS模块正常");


            // 构建位置查询条件
            Criteria criteria = new Criteria();
            // 查询精度：高
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            // 是否查询海拨：否
            criteria.setAltitudeRequired(false);
            // 是否查询方位角 : 否
            criteria.setBearingRequired(false);
            // 是否允许付费：是
            criteria.setCostAllowed(true);
            // 电量要求：低
            criteria.setPowerRequirement(Criteria.POWER_LOW);
            // 返回最合适的符合条件的 provider ，第 2 个参数为 true 说明 , 如果只有一个 provider 是有效的 , 则返回当前

//            locationManager.setTestProviderEnabled("gps", true);

            provider = locationManager.getBestProvider(criteria, true);

            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                // Permission to access the location is missing.
                PermissionUtils.requestPermission((AppCompatActivity) activity, LOCATION_PERMISSION_REQUEST_CODE,
                        Manifest.permission.ACCESS_FINE_LOCATION, true);
            }
            location = locationManager.getLastKnownLocation(provider);

            if(location==null){
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }
            updateWithNewLocation(location);

            //每隔20秒 发送GPS请求
            locationManager.requestLocationUpdates(provider, 20000, 0, new LocationListener() {
                //位置发生改变自动刷新并保存到sharePreference.xml
                @Override
                public void onLocationChanged(Location location) {
                    updateWithNewLocation(location);
                }

                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {

                }

                @Override
                public void onProviderEnabled(String provider) {

                }

                @Override
                public void onProviderDisabled(String provider) {
                    updateWithNewLocation(null);
                }
            });

        } else {
            ToastMsg.showToastMsg(activity, activity.getString(R.string.shop_detail_setting_tips));
//            Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
//            activity.startActivityForResult(intent, 0);
        }

    }


    private void updateWithNewLocation(Location location) {
        // TODO Auto-generated method stub
//        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)
//                != PackageManager.PERMISSION_GRANTED) {
//            // Permission to access the location is missing.
//            PermissionUtils.requestPermission((AppCompatActivity) activity, LOCATION_PERMISSION_REQUEST_CODE,
//                    Manifest.permission.ACCESS_FINE_LOCATION, true);
//        }
//
//        while(location == null){
//            locationManager.requestLocationUpdates(provider, 2000, (float) 0.1, locationListener);
//        }
        double latitude = 0;
        double longitude = 0;
        if (location != null) {
            latitude = location.getLatitude(); // 经度
            longitude = location.getLongitude(); // 纬度
            Log.d("cy", "经度:" + location.getLongitude() + "维度：" + location.getLatitude());
            PreferencesHelper.getInstance().setString(PreferencesHelper.CURRENT_LOCATION_LAT, latitude + "");
            PreferencesHelper.getInstance().setString(PreferencesHelper.CURRENT_LOCATION_LNG, longitude + "");
        }
    }


    /**
     * 通过起点终点，组合成url
     *
     * @param origin
     * @param dest
     * @param travellingMode
     * @return 请求路径为：https://maps.googleapis.com/maps/api/directions/json?origin=22.604823,114.053742&destination=22
     * .904737,114.153556&sensor=false&mode=driving&waypoints=40.036675,116.32885
     * <p/>
     * params如下：
     * origin(必要)您要计算导航路径的起始位置，可以是地址或经纬度。
     * <p/>
     * destination (必要)您要计算导航路径的终止位置，可以是地址或经纬度。
     * <p/>
     * mode(选用，默认值：driving)指定计算导航时使用的交通模式。
     * <p/>
     * driving表示使用标准行车导航。
     * <p/>
     * walking 要求使用人行道及行人步行导航。
     * <p/>
     * bicycling 要求使用自行车导航。(只适用于美国)
     * <p/>
     * waypoints (选用) 指定导航路径要经过的地点。地点可以指定为经纬度坐标或可进行地理编码的地址。
     * <p/>
     * alternatives (选用)true 时，表示请求导航的回应中提供一个以上的路线。这个可能延长服务器的请求耗时。
     * <p/>
     * avoid(选用) 表示导航路径要避开的地点。这个参数可以是下面的2个值︰
     * <p/>
     * tolls 表示路径避开收费站。
     * <p/>
     * highways 表示路径避开高速公路。
     * <p/>
     * units (选用)指定显示的单位。
     * <p/>
     * metric 使用标准单位，公里和公尺。
     * <p/>
     * imperial 使用英式单位，英里和英尺。
     * <p/>
     * region (选用)将区域代码指定为ccTLD([顶层网域])的两位字元值。
     * <p/>
     * language (选用)路径传回时使用的语言。如果系统不支持设置的语言，那么系统会使用浏览器设置的语言进行返回。
     * zh-CN 简体汉语
     * en-US 英语
     * <p/>
     * sensor (必要) 指出导航的请求设备是否附有位置感应器。这个值必须是 true 或 false。
     */
    public String getDirectionsUrl(LatLng origin, LatLng dest, String travellingMode) {

        String str_origin = "origin=" + origin.latitude + ","
                + origin.longitude;

        String str_dest = "destination=" + dest.latitude + "," + dest.longitude;

        String sensor = "sensor=false";

        String mode = "mode=" + travellingMode;

        //waypoints,116.32885,40.036675
//        String waypointLatLng = "waypoints=" + "22.704823" + "," + "114.053742";

        String parameters = str_origin + "&" + str_dest + "&" + sensor + "&"
                + mode;

        String output = "json";

        String url = "https://maps.googleapis.com/maps/api/directions/"
                + output + "?" + parameters;
        System.out.println("getDerectionsURL--->: " + url);
        return url;
    }

    /***
     * 该方法通过携带经纬度的url请求得到json数据
     *
     * @param strUrl
     * @return
     * @throws IOException
     */
    public static String downloadUrl(String strUrl) throws IOException {
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(strUrl);

            urlConnection = (HttpURLConnection) url.openConnection();

            urlConnection.connect();

            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(
                    iStream));

            StringBuffer sb = new StringBuffer();

            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            data = sb.toString();

            br.close();

        } catch (Exception e) {
            Log.d("Except downloading url", e.toString());
        } finally {
            iStream.close();
            urlConnection.disconnect();
        }
        System.out.println("url:" + strUrl + "---->   downloadurl:" + data);
        return data;
    }


    /***
     * 接收JSONObject，解析结果集
     *
     * @param jObject
     * @return
     */
    public List<List<HashMap<String, String>>> parse(JSONObject jObject) {

        List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
        JSONArray jRoutes = null;
        JSONArray jLegs = null;
        JSONArray jSteps = null;

        try {

            jRoutes = jObject.getJSONArray("routes");

            /** Traversing all routes */
            for (int i = 0; i < jRoutes.length(); i++) {
                jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
                List path = new ArrayList<HashMap<String, String>>();

                /** Traversing all legs */
                for (int j = 0; j < jLegs.length(); j++) {
                    jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps");

                    /** Traversing all steps */
                    for (int k = 0; k < jSteps.length(); k++) {
                        String polyline = "";
                        polyline = (String) ((JSONObject) ((JSONObject) jSteps
                                .get(k)).get("polyline")).get("points");
                        List<LatLng> list = decodePoly(polyline);

                        /** Traversing all points */
                        for (int l = 0; l < list.size(); l++) {
                            HashMap<String, String> hm = new HashMap<String, String>();
                            hm.put("lat",
                                    Double.toString(((LatLng) list.get(l)).latitude));
                            hm.put("lng",
                                    Double.toString(((LatLng) list.get(l)).longitude));
                            path.add(hm);
                        }
                    }
                    routes.add(path);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e) {
        }
        return routes;
    }

    /***
     * 封装成点的集合
     * Method to decode polyline points Courtesy :
     * jeffreysambells.com/2010/05/27
     * /decoding-polylines-from-google-maps-direction-api-with-java
     *
     * @param encoded
     * @return
     */
    private List<LatLng> decodePoly(String encoded) {

        List<LatLng> poly = new ArrayList<LatLng>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng p = new LatLng((((double) lat / 1E5)),
                    (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }


    /**
     * 使用异步操作AsynTask实现downurl json 数据
     * 根据经纬度反向解析地址，有时需要多尝试几次
     * 注意:如果在 24 小时时段内收到来自一个 IP 地址超过 2500 个地址解析请求， 或从一个 IP
     * 地址提交的地址解析请求速率过快，Google 地图 API 编码器将用 620 状态代码开始响应。 如果地址解析器的使用仍然过多，则从该 IP
     * 地址对 Google 地图 API 地址解析器的访问可能被永久阻止。
     */
    public class DownloadTask extends AsyncTask<String, Void, String> {

        // Downloading data in non-ui thread
        @Override
        protected String doInBackground(String... url) {

            String data = "";

            try {
                data = downloadUrl(url[0]);
                Log.d("cy", "url[0]为：" + url[0] + "");
                Log.d("cy", "DownloadTask data为：" + data + "");
            } catch (Exception e) {
                Log.d("Background Task", e.toString());
            }
            return data;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            ParserTask parserTask = new ParserTask();

            Log.d("cy", "DownloadTask result为：" + result + "" + result.length());

            if (mStopRefreshAnim != null) {
                mStopRefreshAnim.stopRefresh();
            }
            // Invokes the thread for parsing the JSON data
            if (TextUtils.isEmpty(result)) {
                return;
            }


            parserTask.execute(result);

        }
    }


    /**
     * 异步操作，转换得到的 Google GEO json数据，得到formatted_address当前地址信息
     */
    public class ParserTask extends
            AsyncTask<String, Integer, List<HashMap<String, String>>> {

        public ParserTask() {
        }


        // Parsing the data in non-ui thread
        @Override
        protected List<HashMap<String, String>> doInBackground(
                String... jsonData) {

            JSONObject jObject;
            JSONArray jsonArray;
            List<HashMap<String, String>> routes = null;

            try {
                jObject = new JSONObject(jsonData[0]);
                Log.d("cy", "ParserTask jsonData[0]为：" + jsonData[0] + "");
                System.out.println("jObject:" + jObject);
                jsonArray = (JSONArray) jObject.get("results");
                Log.d("cy", "ParserTask jsonArray为：" + jsonArray + "");

                JSONObject object = (JSONObject) jsonArray.get(0);
                Log.d("cy", "formatted_address:" + object.get("formatted_address"));
                addressDetail = (String) object.get("formatted_address");
                JSONArray addressArray = (JSONArray) object.get("address_components");
                for (int i = 0; i <= jsonArray.length(); i++) {
                    JSONObject addressObject = (JSONObject) addressArray.get(i);
                    addressDatas.add((String) addressObject.get("long_name"));
                    Log.d("cy", "long_name:" + addressObject.get("long_name"));
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
            return routes;
        }

        @Override
        protected void onPostExecute(List<HashMap<String, String>> result) {

            Log.d("cy", "ParserTask result为：" + result + "");

            if (myLocationListener != null && addressDetail != null) {
                myLocationListener.getLatestAddress(addressDetail);
                Log.d("cy", "ParserTask latestAddress:" + addressDetail);

            }


            if (myLocationCityListener != null && addressDatas != null) {
                myLocationCityListener.getLatestCityAddress(getCurrentCity());
                Log.d("cy", "ParserTask latestCityAddress:" + addressDetail);
            }
        }
    }

    /**
     * 获得当前维度
     */
    public String getCurrentLat() {
        return PreferencesHelper.getInstance().getString(PreferencesHelper.CURRENT_LOCATION_LAT);
    }

    /**
     * 根据当前的经纬度获得逆编码地址
     */
    public void getLatestGeoAddress() {
        new DownloadTask().execute(String.format("http://maps.google.com/maps/api/geocode/json?latlng=%s," +
                "%s&sensor=true&language=%s", getCurrentLat(), getCurrentLng(), getCurrentLang()));
    }

    /**
     * 获得当前经度
     */
    public String getCurrentLng() {
        return PreferencesHelper.getInstance().getString(PreferencesHelper.CURRENT_LOCATION_LNG);
    }


    public String getCurrentLang() {
//        Log.d("cy","当前语言："+activity.getResources().getConfiguration().locale.getLanguage());
//        return activity.getResources().getConfiguration().locale.getLanguage();
        Log.d("cy", "当前语言：" + SelectLanguageUtils.getCurrentLanguageCode(activity));
        return SelectLanguageUtils.getCurrentLanguageCode(activity);
    }


    public String getCurrentCity() {
        String str = "";
        if (addressDatas != null && addressDatas.size() > 0)
            str = addressDatas.get(addressDatas.size() - 3);//倒数第三个为当前城市
        Log.d("cy", "当前城市为：" + str);
        return str;
    }


    public boolean checkGoogleMap() {
        boolean isInstallGMap = false;
        List<PackageInfo>
                packs = activity.getPackageManager().getInstalledPackages(0);
        for (int i = 0; i < packs.size(); i++) {
            PackageInfo p = packs.get(i);

//            if (p.versionName == null) { // system packages
//                continue;
//            }
            if ("com.google.android.apps.maps".equals(p.packageName)) {
                Log.d("cy", "PackageInfo:" + p.packageName);
                isInstallGMap = true;
                Log.d("cy", "com.google.android.apps.maps install");
                break;
            }
        }
        return isInstallGMap;
    }


    private StopRefreshInterface mStopRefreshAnim;

    public void setStopRefreshAnim(StopRefreshInterface stopRefreshAnim) {
        mStopRefreshAnim = stopRefreshAnim;
    }

    public static double getDistance(double lat1, double lon1, double lat2, double lon2) {
        float[] results = new float[1];
        Location.distanceBetween(lat1, lon1, lat2, lon2, results);
        return results[0];
    }

    public static String getBetweenDistance(double distance) {
        return DistanceUtils.formatMeter(distance);
    }
}
